package com.shsh.safemanage.util;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Util {
	public static String generateRandomPassword(int pwd_len) {
		final int maxNum = 36;
		int i;
		int count = 0;
		char[] str = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
				'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

		StringBuffer pwd = new StringBuffer("");
		Random r = new Random();
		while (count < pwd_len) {

			i = Math.abs(r.nextInt(maxNum));

			if (i >= 0 && i < str.length) {
				pwd.append(str[i]);
				count++;
			}
		}

		return pwd.toString();
	}

	public static String isoToUTF8(String str) {
		try {
			return new String(str.getBytes("ISO8859-1"), "UTF-8");
		} catch (Exception e) {
			return "";
		}
	}

	public static String generateAlipayUsername() {
		Date date = new Date();
		DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");

		return "ALI" + df.format(date);
	}

	public static String generateQQUsername() {
		Date date = new Date();
		DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");

		return "QQ" + df.format(date);
	}

	public static boolean isNumeric(String str) {
		Pattern pattern = Pattern.compile("[0-9]*");
		Matcher isNum = pattern.matcher(str);
		if (isNum.matches()) {
			return true;
		} else {
			return false;
		}
	}

	public static boolean isDate(String strDate) {
		Pattern pattern = Pattern.compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|"
				+ "(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|"
				+ "(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|"
				+ "([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?"
				+ "((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|"
				+ "(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|"
				+ "(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|"
				+ "([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$");
		Matcher m = pattern.matcher(strDate);
		if (m.matches()) {
			return true;
		} else {
			return false;
		}
	}

	public static boolean isEmail(String email) {
		Pattern p = Pattern.compile("\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*");
		Matcher m = p.matcher(email);
		return m.find();
	}

	public static boolean isMobileNumber(String mobile) {
		Pattern p = Pattern.compile("/^0{0,1}(13[0-9]|15[0-9])[0-9]{8}$/");
		Matcher m = p.matcher(mobile);
		return m.find();
	}

	public static boolean isNullOrEmpty(String str) {
		return str == null || str.length() == 0;
	}

	public static String generateRegisterCode() {
		StringBuilder sb = new StringBuilder();
		Random random = new Random();
		for (int i = 0; i < 30; i++) {
			sb.append("" + random.nextInt(10));
		}

		return sb.toString();
	}

	public static String generateCheckCode(int len) {
		StringBuilder sb = new StringBuilder();
		Random random = new Random();
		for (int i = 0; i < len; i++) {
			int code = random.nextInt(36);
			if (code < 10) {
				sb.append("" + code);
			} else {
				char ch = (char) ('a' + (code - 10));
				sb.append(ch);
			}
		}

		return sb.toString();
	}

	public static String convertLongPriceToStr(Long price) {
		StringBuilder sb = new StringBuilder();
		sb.append(price / 100);
		sb.append(".");
		sb.append(price % 100);

		return sb.toString();
	}

	public static int countStrCharNum(String str) {
		if (str == null) {
			return 0;
		}

		int count = 0;
		for (int i = 0; i < str.length(); i++) {
			char ch = str.charAt(i);
			if ((int) ch > 0 && (int) ch < 128) {
				count++;
			} else {
				count += 2;
			}
		}

		return count;
	}

	public static String substrByCharLen(String str, int len) {
		if (str == null) {
			return null;
		}

		int count = 0;
		for (int i = 0; i < str.length(); i++) {
			char ch = str.charAt(i);
			if ((int) ch >= 0 && (int) ch <= 255) {
				count++;
			} else {
				count += 2;
			}

			if (count >= len) {
				return str.substring(0, i) + "...";
			}
		}

		return str;
	}

	public static String toJSONStringWithQuotation(Map<String, Object> map) {
		StringBuilder sb = new StringBuilder();

		sb.append("{");
		Iterator<Map.Entry<String, Object>> itr = map.entrySet().iterator();
		int i = 0;
		while (itr.hasNext()) {
			Map.Entry<String, Object> entry = itr.next();
			if (entry.getValue() != null && entry.getKey() != null) {
				if (i == 0) {
					sb.append("\"" + entry.getKey() + "\":\"" + entry.getValue().toString() + "\"");
				} else {
					sb.append(",\"" + entry.getKey() + "\":\"" + entry.getValue().toString() + "\"");
				}

				i++;
			}
		}
		sb.append("}");

		return sb.toString();
	}

	public static String toJSONString(Map<String, Object> map) {
		StringBuilder sb = new StringBuilder();

		sb.append("{");
		Iterator<Map.Entry<String, Object>> itr = map.entrySet().iterator();
		int i = 0;
		while (itr.hasNext()) {
			Map.Entry<String, Object> entry = itr.next();
			if (entry.getValue() != null && entry.getKey() != null) {
				if (i == 0) {
					sb.append("" + entry.getKey() + ":\"" + Util.strToJSON(entry.getValue().toString()) + "\"");
				} else {
					sb.append("," + entry.getKey() + ":\"" + Util.strToJSON(entry.getValue().toString()) + "\"");
				}

				i++;
			}
		}
		sb.append("}");

		return sb.toString();
	}

	public static String strToJSON(String str) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < str.length(); i++) {
			char ch = str.charAt(i);

			switch (ch) {
			case '\"':
				sb.append("\\\"");
				break;
			case '\'':
				sb.append("\\\'");
				break;
			case '\\':
				sb.append("\\\\");
				break;
			case '/':
				sb.append("\\/");
				break;
			case '\b':
				sb.append("\\b");
				break;
			case '\f':
				sb.append("\\f");
				break;
			case '\n':
				sb.append("\\n");
				break;
			case '\r':
				sb.append("\\r");
				break;
			case '\t':
				sb.append("\\t");
				break;
			default:
				sb.append(ch);
			}
		}

		return sb.toString();
	}

	private static DateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
	private static DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");

	public static String formatDateTime(Calendar calendar) {
		if (calendar == null) {
			return "";
		}

		return formatDateTime(calendar.getTime());
	}

	public static String formatDateTime(Date date) {
		if (date == null) {
			return "";
		}
		return dateTimeFormat.format(date);
	}

	public static String formatTime(Date date) {
		if (date == null) {
			return "";
		}
		return timeFormat.format(date);
	}

	public static String formatDate(Date date) {
		if (date == null) {
			return "";
		}
		return dateFormat.format(date);
	}

	public static String formatDate(Calendar cal) {
		if (cal == null) {
			return "";
		}
		return dateFormat.format(cal.getTime());
	}

	public static Calendar convertStrToDateTime(String bidTimeStr) {
		if (Util.isNullOrEmpty(bidTimeStr)) {
			return null;
		}

		Date date = null;
		try {
			date = dateTimeFormat.parse(bidTimeStr);
		} catch (Exception e) {
			return null;
		}

		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		return cal;
	}

	public static Calendar convertStrToDate(String dateStr) {
		if (Util.isNullOrEmpty(dateStr)) {
			return null;
		}

		Date date = null;
		try {
			date = dateFormat.parse(dateStr);
		} catch (Exception e) {
			return null;
		}

		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		return cal;
	}

	public static String formatPrice(Long fen) {
		if (fen == null) {
			return "--.--";
		}

		StringBuilder sb = new StringBuilder();
		if (fen < 0) {
			sb.append("-");
			fen = -fen;
		}
		long fen1 = fen % 100;
		sb.append("" + fen / 100);
		sb.append(".");
		if (fen1 < 10) {
			sb.append("0" + fen1);
		} else {
			sb.append("" + fen1);
		}

		return sb.toString();
	}

	public static String formatPage(int len, String pageStr) {
		StringBuilder sb = new StringBuilder();
		for (int i = pageStr.length(); i < len; i++) {
			sb.append("0");
		}
		sb.append(pageStr);

		return sb.toString();
	}

	public static long countSecondFromNow(Calendar toTime, Calendar now) {
		return (long) (toTime.getTimeInMillis() - now.getTimeInMillis()) / 1000;
	}

	public static long countSecondFromNow(Calendar toTime, Date now) {
		return (long) (toTime.getTimeInMillis() - now.getTime()) / 1000;
	}

	public static long countSecondFromNow(Date toTime, Calendar now) {
		return (long) (toTime.getTime() - now.getTimeInMillis()) / 1000;
	}

	public static long countSecondFromNow(Date toTime, Date now) {
		return (long) (toTime.getTime() - now.getTime()) / 1000;
	}

	/**
	 * Calculate page amount.
	 * 
	 * @param pageSize
	 * @param resultCount
	 * @return
	 */
	public static int getPageCount(int pageSize, int resultCount) {
		if (resultCount == 0) {
			return 1;
		}

		if (resultCount % pageSize == 0) {
			return resultCount / pageSize;
		} else {
			return resultCount / pageSize + 1;
		}
	}

	public static String generateInCluse(List<Object> lst, boolean needQuotation) {
		if (lst == null) {
			return generateInCluse((Object[]) null, needQuotation);
		} else {
			return generateInCluse(lst.toArray(), needQuotation);
		}
	}

	public static String generateInCluse(Object[] objs, boolean needQuotation) {
		StringBuilder sb = new StringBuilder();
		sb.append("");
		if (objs == null) {
			return "";
		}

		if (objs.length == 0) {
			return " ('')";
		}

		sb.append(" (");
		for (Object obj : objs) {
			String str = obj.toString();
			if (needQuotation) {
				sb.append("'");
			}
			sb.append(str);
			if (needQuotation) {
				sb.append("',");
			} else {
				sb.append(",");
			}
		}
		sb.deleteCharAt(sb.length() - 1);
		sb.append(")");

		return sb.toString();
	}

	public static String toDateString(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);

		int theYear = calendar.get(Calendar.YEAR);
		int theMonth = calendar.get(Calendar.MONTH);
		int theDate = calendar.get(Calendar.DATE);

		StringBuilder sb = new StringBuilder();
		sb.append("" + theYear);
		sb.append((theMonth < 10) ? "0" + theMonth : "" + theMonth);
		sb.append((theDate < 10) ? "0" + theDate : "" + theDate);

		return sb.toString();
	}

	public static String generateDateString(int shift, String format) {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DATE, shift);

		SimpleDateFormat df = new SimpleDateFormat(format);

		return df.format(calendar.getTime());
	}

	public static String[] toStringArray(String str, String split) {
		if (str == null || str.trim().length() == 0) {
			return new String[] {};
		}

		return str.split(split);
	}

	public static long[] toLongArray(String str, String split) {
		String[] strs = toStringArray(str, split);
		long[] rtn = new long[strs.length];

		for (int i = 0; i < strs.length; i++) {
			try {
				rtn[i] = Long.parseLong(strs[i]);
			} catch (Exception e) {

			}
		}

		return rtn;
	}

	/**
	 * make form submit to valid html encode
	 * 
	 * @param s
	 * @return
	 */
	public static String toHtmlEncode(String s) {
		if (s == null) {
			return "";
		}

		StringBuffer strBuffer = new StringBuffer();
		int j = s.length();
		for (int i = 0; i < j; i++) {
			char c = s.charAt(i);
			switch (c) {
			case 60:
				strBuffer.append("&lt;");
				break;
			case 62:
				strBuffer.append("&gt;");
				break;
			case 38:
				strBuffer.append("&amp;");
				break;
			case 34:
				strBuffer.append("&quot;");
				break;
			case 169:
				strBuffer.append("&copy;");
				break;
			case 174:
				strBuffer.append("&reg;");
				break;
			case 165:
				strBuffer.append("&yen;");
				break;
			case 8364:
				strBuffer.append("&euro;");
				break;
			case 8482:
				strBuffer.append("&#153;");
				break;
			case 13:
				if (i < j - 1 && s.charAt(i + 1) == 10) {
					strBuffer.append("<br />");
					i++;
				}
				break;
			case 32:
				strBuffer.append("&nbsp");
				break;
			default:
				strBuffer.append(c);
				break;
			}
		}

		return strBuffer.toString();
	}

	public static String toString(Long[] vals, String split, String quot) {
		if (vals == null || vals.length == 0) {
			return "";
		}

		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < vals.length - 1; i++) {
			sb.append(quot).append(vals[i]).append(quot).append(split);
		}
		sb.append(quot).append(vals[vals.length - 1]).append(quot);

		return sb.toString();
	}

	public static String toString(long[] vals, String split, String quot) {
		if (vals == null || vals.length == 0) {
			return "";
		}

		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < vals.length - 1; i++) {
			sb.append(quot).append(vals[i]).append(quot).append(split);
		}
		sb.append(quot).append(vals[vals.length - 1]).append(quot);

		return sb.toString();
	}

	public static String toString(String[] vals, String split, String quot) {
		if (vals == null || vals.length == 0) {
			return "";
		}

		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < vals.length - 1; i++) {
			sb.append(quot).append(vals[i]).append(quot).append(split);
		}
		sb.append(quot).append(vals[vals.length - 1]).append(quot);

		return sb.toString();
	}

	public static boolean isChinese(char c) {
		Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
		if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
				|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
				|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
			return true;
		}

		return false;
	}

	public static boolean isChinese(String strName) {
		char[] ch = strName.toCharArray();
		for (int i = 0; i < ch.length; i++) {
			char c = ch[i];
			if (!isChinese(c)) {
				return false;
			}
		}

		return true;
	}

	/**
	 * 
	 * @return 
	 *         rtn[0]=year;rtn[1]=month;rtn[2]=date;rtn[3]=hour;rtn[4]=minute;rtn
	 *         [5]=second;
	 */
	public static int[] getCurrentDate() {
		return getDate(Calendar.getInstance());
	}

	/**
	 * 
	 * @return 
	 *         rtn[0]=year;rtn[1]=month;rtn[2]=date;rtn[3]=hour;rtn[4]=minute;rtn
	 *         [5]=second;
	 */
	public static int[] getDate(Calendar cal) {
		if (cal == null) {
			return new int[] { 0, 0, 0, 0, 0, 0 };
		}
		int[] rtn = new int[6];
		rtn[0] = cal.get(Calendar.YEAR);
		rtn[1] = cal.get(Calendar.MONTH) + 1;
		rtn[2] = cal.get(Calendar.DAY_OF_MONTH);
		rtn[3] = cal.get(Calendar.HOUR_OF_DAY);
		rtn[4] = cal.get(Calendar.MINUTE);
		rtn[5] = cal.get(Calendar.SECOND);

		return rtn;
	}

	public static int[] getDate(Calendar cal, int field, int offset) {
		cal.add(field, offset);
		return getDate(cal);
	}

	public static int getCurrentMonthEnd() {
		int[] date = getCurrentDate();
		return getMonthEnd(date[0], date[1]);
	}

	public static int getWorkingday(int year, int month) {
		Calendar calStart = getCalendar(new int[] { year, month, 1, 0, 0, 0 });
		Calendar calEnd = getCalendar(new int[] { year, month, getMonthEnd(year, month), 23, 59, 59 });

		return getWorkingDay(calStart, calEnd);
	}

	public static int getDaysBetween(Calendar d1, Calendar d2) {
		if (d1.after(d2)) { // swap dates so that d1 is start and d2 is end
			Calendar swap = d1;
			d1 = d2;
			d2 = swap;
		}
		int days = d2.get(Calendar.DAY_OF_YEAR) - d1.get(Calendar.DAY_OF_YEAR);
		int y2 = d2.get(Calendar.YEAR);
		if (d1.get(Calendar.YEAR) != y2) {
			d1 = (Calendar) d1.clone(); //
			do {
				days += d1.getActualMaximum(Calendar.DAY_OF_YEAR);
				d1.add(Calendar.YEAR, 1);
			} while (d1.get(Calendar.YEAR) != y2);
		}
		return days;
	}

	public static int getWorkingDay(Calendar d1, Calendar d2) {
		int result = -1;
		if (d1.after(d2)) { // swap dates so that d1 is start and d2 is end
			Calendar swap = d1;
			d1 = d2;
			d2 = swap;
		}
		int chargeStartDate = 0;
		int chargeEndDate = 0;

		int stmp;
		int etmp;
		stmp = 7 - d1.get(Calendar.DAY_OF_WEEK);
		etmp = 7 - d2.get(Calendar.DAY_OF_WEEK);
		if (stmp != 0 && stmp != 6) {
			chargeStartDate = stmp - 1;
		}
		if (etmp != 0 && etmp != 6) {
			chargeEndDate = etmp - 1;
		}
		result = (getDaysBetween(getNextMonday(d1), getNextMonday(d2)) / 7) * 5 + chargeStartDate - chargeEndDate;

		return result;
	}

	public static Calendar getNextMonday(Calendar date) {
		Calendar result = null;
		result = date;
		do {
			result = (Calendar) result.clone();
			result.add(Calendar.DATE, 1);
		} while (result.get(Calendar.DAY_OF_WEEK) != 2);
		return result;
	}

	/**
	 * 
	 * @param time
	 * @return
	 */
	public static Calendar getCalendar(int[] time) {
		if (time.length < 6) {
			throw new RuntimeException("Time length should be 6");
		}
		String str = time[0] + "-" + time[1] + "-" + time[2] + " " + time[3] + ":" + time[4] + ":" + time[5];
		try {
			Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(str);
			Calendar cal = Calendar.getInstance();
			cal.setTime(date);
			return cal;
		} catch (ParseException e) {
			return Calendar.getInstance();
		}
	}

	/**
	 * 
	 * @param year
	 * @param month
	 * @return
	 */
	public static int getMonthEnd(int year, int month) {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.MONTH, month - 1);

		return cal.getActualMaximum(Calendar.DAY_OF_MONTH);
	}

	public static int[] getPreviousYearMonth(int year, int month) {
		// Calculate previous month.
		int previousYear = year;
		int previousMonth;
		if (month == 1) {
			previousYear = year - 1;
			previousMonth = 12;
		} else {
			previousMonth = month - 1;
		}

		return new int[] { previousYear, previousMonth };
	}

	/**
	 * 
	 * @param month
	 * @return 0:1,4,7,10; 1:2,5,8,11; 2:3,6,9,12;
	 */
	public static int getMonthIndexInSeason(int month) {
		return (month - 1) % 3;
	}

	public static int[] getSeasonMonth(int month) {
		int monthIndex = getMonthIndexInSeason(month);
		int[] season = new int[] { (month - (monthIndex - 0)) % 13, (month - (monthIndex - 1)) % 13, (month - (monthIndex - 2)) % 13 };
		return season;
	}

	public static String formatGrade(Integer grade) {
		if (grade == null) {
			return "";
		} else if (grade % 100 == 0) {
			return String.valueOf((grade / 100));
		} else {
			return String.valueOf((grade / 100.0));
		}
	}

	public static String formatRate(Integer rate) {
		if (rate == null) {
			return "";
		} else if (rate % 100 == 0) {
			return String.valueOf((rate / 100));
		} else {
			return String.valueOf((rate / 100.0));
		}
	}

	public static String formatGrade(Long grade) {
		if (grade == null) {
			return "";
		} else if (grade % 100 == 0) {
			return String.valueOf((grade / 100));
		} else {
			return String.valueOf((grade / 100.0));
		}
	}

	public static long[] getPeriod(long minutes) {
		long hours = minutes / 60;
		long day = minutes / (24 * 60);
		return new long[] { day, hours % 24, minutes % 60 };
	}

	public static String getDisplay(String value, String defaultValue) {
		return value == null ? defaultValue : value;
	}

	public static String getDisplay(Integer value, String defaultValue) {
		return value == null ? defaultValue : String.valueOf(value);
	}

	public static String getRange(int currentData, int previousData) {
		int internal = currentData - previousData;
		if (previousData == 0) {
			return "/";
		}

		return String.valueOf(internal * 100 / previousData) + "%";
	}

	public static byte[] getBytes(Serializable obj) throws Exception {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(out);
		oos.writeObject(obj);
		oos.flush();
		oos.close();
		out.close();

		return out.toByteArray();
	}

	public static Long extractEntityID(String value, String prefix) throws Exception {
		String str = value.substring(prefix.length());
		return Long.parseLong(str);
	}
}
